#include "render_system/vertex_array_object.h"

#include <exception>

#include "render_system/gl_header.h"
#include "render_system/basic_define.h"

#include "utility.h"


void VertexArrayObject::addAttribArray( const int attribID, BufferObjectPtr pBufferObj )
{
    try
    {
        if (0 > attribID)
        {
            return;
        }
        _attribMap[attribID] = pBufferObj;
    }
    catch(const std::exception& e)
    {
        Log::error(e.what());
        throw;
    }
}

void VertexArrayObject::_create()
{
    try
    {
        GLuint vaoID;
        glGenVertexArrays(1, &vaoID);
        if (0 == vaoID)
        {
            throw std::exception("fail to generate VAO ID.");
        }
        _uID = vaoID;
        glBindVertexArray(vaoID);

        for (auto item = _attribMap.begin(); item != _attribMap.end(); item++)
        {
            auto handle = item->first;
            auto pbff = item->second;

            glEnableVertexAttribArray(handle);
            pbff->bind();
            glVertexAttribPointer(
                handle,
                pbff->channels(),
                pbff->glConponentType(),
                GL_FALSE,
                0,
                (GLvoid*)NULL);
        }
        glBindVertexArray(0);
    }
    catch(const std::exception& e)
    {
        Log::error(e.what());
        throw;
    }
}

VertexArrayObject::~VertexArrayObject()
{
    try
    {
        if (0 != _uID)
        {
            glDeleteVertexArrays(1, &_uID);
            _uID = 0;
        }
    }
    catch(const std::exception& e)
    {
        Log::error(e.what());
        throw;
    }
}

void VertexArrayObject::bind()
{
    if (0 == _uID)
    {
        _create();
    }

    if (0 != _uID)
    {
        glBindVertexArray(_uID);
    }
}

void VertexArrayObject::unBind()
{
    if (0 != _uID)
    {
        glBindVertexArray(0);
    }
}

VertexArrayObject::VertexArrayObject()
    : _uID(0)
{

}

